package artist

import (
	"context"
	"fmt"
	log2 "github.com/name5566/leaf/log"
	"go.mongodb.org/mongo-driver/bson"
	"server/db"
)

type ArtistDao struct {
	db *db.MongoMiddleware
}

// Constants
const (
	TBL_ATTIST = "t_artist"
	// Max allowed data per query
	DATA_MAX_IN = 100
)

func NewArtistDao() *ArtistDao {
	return &ArtistDao{
		db: db.Db,
	}
}

func (a *ArtistDao) GetArtistsByUidStatus(uid string) {
	query := bson.M{"user_id": uid}
	var result Artists
	err := a.db.FindOne(TBL_ATTIST, query, &result)
	if err != nil {
		log2.Error("err message is %v", err)
	}
}

func (a *ArtistDao) UpArtistsBeautyLv(userId string, cardId int32, BeautyLv int64) error {
	filter := bson.M{
		"user_id":    userId,
		"artists_id": cardId,
	}
	update := bson.M{
		"$set": bson.M{
			"beauty_lv": BeautyLv,
		},
	}
	err := a.db.Update(TBL_ATTIST, filter, update)
	if err != nil {
		return err
	}
	return nil
}
func (a *ArtistDao) Insert(userId string, data Artists) error {
	data.UserId = userId
	err := a.db.Insert(TBL_ATTIST, data)
	if err != nil {
		return err
	}
	return nil
}

// GetHeroesByUid retrieves heroes by user ID
func (a *ArtistDao) GetArtistsByUid(uid string) ([]Artists, error) {
	var result []Artists
	query := bson.M{"user_id": uid}
	err := a.db.Find(TBL_ATTIST, query, &result)
	if err != nil {
		return nil, err
	}
	return result, nil
}
func (a *ArtistDao) GetRandomArtistByUid(uid string) (Artists, error) {
	var result Artists
	query := bson.M{"user_id": uid}
	err := a.db.RandNum(TBL_ATTIST, query, &result)
	if err != nil {
		return result, err
	}
	return result, nil
}
func (a *ArtistDao) GetUnArtistsNumByUid(uid string) (int64, error) {
	var count int64
	filter := bson.M{"user_id": bson.M{"$ne": ""}}
	count, err := a.db.Client.Collection(TBL_ATTIST).Find(context.Background(), filter).Count()
	if err != nil {
		fmt.Println(err)
		return 0, nil
	}
	return count, err
}
func (v *ArtistDao) UpBeautySkill(userId string, vTid int32, skillList []BeautySkillInfo) error {
	filter := bson.M{
		"user_id":    userId,
		"artists_id": vTid,
	}
	update := bson.M{
		"$set": bson.M{
			"beauty_skill_list": skillList,
		},
	}
	err := db.Db.Update(TBL_ATTIST, filter, update)
	if err != nil {
		return err
	}

	return nil
}
func (v *ArtistDao) UpBeautyXuanChuanJinYan(userId string, vTid int32, xuanChuanJinYan int) error {
	filter := bson.M{
		"user_id":    userId,
		"artists_id": vTid,
	}
	update := bson.M{
		"$set": bson.M{
			"xuan_chuan_jin_yan": xuanChuanJinYan,
		},
	}
	err := db.Db.Update(TBL_ATTIST, filter, update)
	if err != nil {
		return err
	}

	return nil
}
func (v *ArtistDao) UpBeautyCharm(userId string, vTid int32, charm float64) error {
	filter := bson.M{
		"user_id":    userId,
		"artists_id": vTid,
	}
	update := bson.M{
		"$set": bson.M{
			"charm": charm,
		},
	}
	err := db.Db.Update(TBL_ATTIST, filter, update)
	if err != nil {
		return err
	}

	return nil
}
func (v *ArtistDao) UpBeautyIsFirst(userId string, vTid int32, charm int32) error {
	filter := bson.M{
		"user_id":    userId,
		"artists_id": vTid,
	}
	update := bson.M{
		"$set": bson.M{
			"charm": charm,
		},
	}
	err := db.Db.Update(TBL_ATTIST, filter, update)
	if err != nil {
		return err
	}

	return nil
}
func (v *ArtistDao) UpBeautyYinXiaoId(userId string, vTid int32, yinXiaoId int64) error {
	filter := bson.M{
		"user_id":    userId,
		"artists_id": vTid,
	}
	update := bson.M{
		"$set": bson.M{
			"Yin_xiao_id": yinXiaoId,
		},
	}
	err := db.Db.Update(TBL_ATTIST, filter, update)
	if err != nil {
		return err
	}

	return nil
}

// GetHeroByUidHtid retrieves a single hero by user ID and hero type ID
func (a *ArtistDao) GetArtistByUidArtistsId(uid string, cardId int32) (Artists, error) {
	var result Artists
	query := bson.M{"user_id": uid, "artists_id": cardId}
	err := a.db.FindOne(TBL_ATTIST, query, &result)
	if err != nil {
		return result, err
	}
	return result, nil
}

// GetArrHeroByHtid retrieves heroes based on a list of hero type IDs
func (a *ArtistDao) GetArrArtistByHtid(uid string, arrHtid []string) ([]map[string]interface{}, error) {
	var result []map[string]interface{}
	if len(arrHtid) == 0 {
		return result, nil
	}

	chunks := chunkArray(arrHtid, DATA_MAX_IN)
	var finalResult []map[string]interface{}
	for _, chunk := range chunks {
		query := bson.M{"user_id": uid, "htid": bson.M{"$in": chunk}}
		err := a.db.Find(TBL_ATTIST, query, &result)
		if err != nil {
			return nil, err
		}
		finalResult = append(finalResult, result...)
	}

	// Post-process result by mapping 'htid'
	heroesMap := make(map[string]map[string]interface{})
	for _, hero := range finalResult {
		htid := fmt.Sprintf("%v", hero["htid"])
		heroesMap[htid] = hero
	}

	var processedResult []map[string]interface{}
	for _, hero := range heroesMap {
		processedResult = append(processedResult, hero)
	}

	return processedResult, nil
}

// Helper function to split array into smaller chunks
func chunkArray(arr []string, chunkSize int) [][]string {
	var chunks [][]string
	for i := 0; i < len(arr); i += chunkSize {
		end := i + chunkSize
		if end > len(arr) {
			end = len(arr)
		}
		chunks = append(chunks, arr[i:end])
	}
	return chunks
}
